import { nextTick, onMounted, reactive, ref, watch } from 'vue'
import { post, get } from 'server/axios.js'
import { config_list_menu_field_post } from 'server/modules/4802.js'
import { config_list_column_post } from 'server/modules/1890.js'
// import { observeDomResize } from 'utils'
import { debounce } from 'lodash-es'
import Storage from 'utils/Storage.js'
// 定义filter 本地存储key
const STORAGE_FILTER_KEY = 'VXE_COLUMNS_STORAGE_FILTER'

export const tableDom = ref(null)
export const paginate = ref({
  pageNum: 1,
  pageSize: 50,
  total: 0
})

export const useState = () => {
  return reactive({
    vxeColumns: [],
    vxeDatas: [],
    menuListFields: [],
    selectedRowKeys: [],
    selectedRows: [],
    selectedRowsMap: {},
    loading: false,
    exportLoading: false,
    query: {},
    options: [],
    tableId: 'cpsVxeTable'
  })
}
export const useInitState = (props, state) => {
  const { pageSize } = props
  // 默认获取本地的storage
  const { clearStorageFilter, getStorageFilter } = useStorageFilter(
    props,
    state
  )
  clearStorageFilter()
  Object.assign(paginate.value, {
    pageNum: 1,
    pageSize
  })
  Object.assign(state, {
    query: {
      sortList: [],
      ...getStorageFilter(),
      ...props.queryParams
    },
    tableId: props.tableId || props.menuName || 'cpsVxeTable',
    selectedRowKeys: props.selectedRowKeys || [],
    vxeColumns: props.columns || [],
    localApiParams: props.apiParams
      ? JSON.parse(JSON.stringify(props.apiParams))
      : {}
  })
}
/**
 * 计算表格列宽
 * @param {*} column
 * @returns
 */
const useColumnWidth = (column, props) => {
  const { columnName, isSearched, requestStr } = column
  if (props.columnWidth[requestStr]) {
    return props.columnWidth[requestStr]
  }

  let fixedWidth = 0
  for (let i = 0; i < columnName?.length; i++) {
    const charCode = columnName.charCodeAt(i)
    if (charCode >= 0 && charCode <= 128) {
      fixedWidth += 8
    } else {
      fixedWidth += 16
    }
  }
  // 添加两边的间距 5是误差
  fixedWidth += 16 + 5
  //  有筛选
  if (isSearched === 1) {
    fixedWidth += 28
  }
  if (fixedWidth < 160) {
    return 160
  }
  if (fixedWidth > 320) {
    return 320
  }
  return fixedWidth
}

/**
 * 获取表格列
 * @param {*} props
 * @returns
 */
const useGetvxeColumns = (props, state) => {
  const { menuName, columnFixed, hasAction, columnWidth } = props

  // 默认获取本地的storage
  const storageFilterQuery =
    (Storage.getItem(STORAGE_FILTER_KEY) || {})[menuName] || {}
  const ajaxColumnFields = async () => {
    const { data } = await config_list_menu_field_post({
      menuName
    })
    state.menuListFields = data || []
    data?.forEach(item => {
      if (item.headType === 1) {
        item.colgroup = item.childrenList.filter(_ => {
          return _.isSelected === 1
        })
      }
    })
    const columnsField =
      data?.filter(_ => {
        return _.isSelected === 1
      }) || []
    formatTableColumn(columnsField)
  }
  const formatTableColumn = columnsField => {
    let columns = []
    columnsField.length &&
      columnsField.map(item => {
        const parentName = item.columnName
        if (item.colgroup) {
          let childColumns = []
          item.colgroup.map(pitem => {
            const {
              columnName,
              isSearched,
              requestStr,
              searchStr,
              model,
              isBatchQuery,
              freeze,
              needEmpty,
              childrenList,
              notes
            } = pitem
            if (
              !(
                childrenList &&
                childrenList.length > 0 &&
                childrenList.findIndex(ppitem => ppitem.isSelected === 1) === -1
              )
            ) {
              let setFilterConfig = {}
              if (isSearched === 1 && model !== 8) {
                setFilterConfig = {
                  params: {
                    columnName: searchStr,
                    menuName
                  },
                  filterValue: storageFilterQuery[searchStr] || [],
                  model,
                  needEmpty,
                  filtered: true,
                  options: [],
                  notes,
                  slots: {
                    customRender: requestStr + 'CR',
                    title: requestStr + 'CT'
                  }
                }
              }
              const fixed = freeze === 1 ? 'left' : ''
              childColumns.push({
                ...{
                  title: columnName,
                  customeTitle: columnName,
                  isBatchQuery,
                  dataIndex: requestStr,
                  sorter: model === 8,
                  sortable: false,
                  key: searchStr,
                  fixed: columnFixed[requestStr] || fixed || '',
                  notes,
                  slots: {
                    customRender: requestStr + 'CR',
                    title: requestStr + 'CT'
                  },
                  childrenList:
                    childrenList &&
                    childrenList.filter(item => item.isSelected === 1)
                },
                ...setFilterConfig
              })
            }
          })
          item.colgroup = childColumns
          columns.push({
            title: parentName,
            colgroup: item.colgroup
          })
        } else {
          const {
            columnName,
            isSearched,
            requestStr,
            searchStr,
            model,
            isBatchQuery,
            freeze,
            needEmpty,
            childrenList,
            notes
          } = item.colgroup ? item.colgroup : item
          // childrenList不为空，且二级没有被选中的类目，则整个列不展示
          if (
            !(
              childrenList &&
              childrenList.length > 0 &&
              childrenList.findIndex(item => item.isSelected === 1) === -1
            )
          ) {
            let setFilterConfig = {}
            if (isSearched === 1 && model !== 8) {
              setFilterConfig = {
                params: {
                  columnName: searchStr,
                  menuName
                },
                filterValue: storageFilterQuery[searchStr] || [],
                model,
                needEmpty,
                filtered: true,
                options: [],
                notes,
                slots: {
                  customRender: requestStr + 'CR',
                  title: requestStr + 'CT'
                }
              }
            }

            const fixed = freeze === 1 ? 'left' : ''
            columns.push({
              ...{
                title: columnName,
                customeTitle: columnName,
                isBatchQuery,
                dataIndex: requestStr,
                sorter: model === 8,
                sortable: false,
                key: searchStr,
                fixed: columnFixed[requestStr] || fixed || '',
                notes,
                slots: {
                  customRender: requestStr + 'CR',
                  title: requestStr + 'CT'
                },
                childrenList:
                  childrenList &&
                  childrenList.filter(item => item.isSelected === 1)
              },
              ...setFilterConfig
            })
          }
        }
      })

    hasAction && columns.push(renderActionColumn(columns))
    state.vxeColumns = columns
  }
  const renderActionColumn = columns => {
    const mql = window.matchMedia('(max-width: 1400px)')
    let w = 1350
    if (mql.matches) {
      w = 800
    }
    let tableMaxWidth = columns.length * 150,
      customerMaxWidth = 0,
      columnMaxWidth = 0
    if (columnWidth && Object.keys(columnWidth)) {
      customerMaxWidth = Object.keys(columnWidth).reduce((prev, key) => {
        return prev + columnWidth[key]
      }, 0)
    }
    columnMaxWidth =
      tableMaxWidth > customerMaxWidth ? tableMaxWidth : customerMaxWidth
    let actionFixed = null
    if (Object.keys(columnFixed).includes('action')) {
      actionFixed = columnFixed['action']
    } else if (columnMaxWidth > w) {
      actionFixed = 'right'
    }

    return {
      title: '操作',
      key: 'action',
      minWidth: columnWidth.action || 180,
      align: 'center',
      fixed: actionFixed,
      slots: { customRender: 'action' }
    }
  }
  ajaxColumnFields()
}
/**
 * 处理表格筛选条件本地存储
 * @param {*} props
 * @param {*} state
 */
/**
 * 处理表格筛选条件本地存储
 * @param {*} props
 * @param {*} state
 */
const useStorageFilter = (props, state) => {
  const { menuName } = props
  const { query } = state
  const storage = Storage.getItem(STORAGE_FILTER_KEY) || {}
  const clearStorageFilter = () => {
    if (!props.filterStorage) {
      delete storage[menuName]
      Storage.setItem(STORAGE_FILTER_KEY, storage)
    }
  }
  const setStorageFilter = () => {
    if (props.filterStorage) {
      storage[menuName] = query
      Storage.setItem(STORAGE_FILTER_KEY, storage)
    }
  }
  const getStorageFilter = () => {
    return storage[menuName] || {}
  }
  return {
    clearStorageFilter,
    setStorageFilter,
    getStorageFilter
  }
}
/**
 * 获取过滤筛选条件
 */
const useFilterParams = function (state) {
  const query = { sortList: [] }
  const columns = state.vxeColumns.reduce((prev, cur) => {
    return [...prev, ...(cur.colgroup ? cur.colgroup : [cur])]
  }, [])
  columns.forEach(_ => {
    const obj = _
    if (obj.desc) {
      query.sortList.push({
        desc: obj.desc,
        field: obj.dataIndex
      })
    }
    if (obj.isBatch) {
      query[obj.key] = obj.batchTags
    } else {
      if (obj.needEmpty === 1) {
        if (obj.isBlank) {
          const index = obj.filterValue.findIndex(item => item === '')
          index === -1 && obj.filterValue.push('')
        } else {
          obj.filterValue = obj.filterValue.filter(v => v !== '')
        }
      }
      if (obj.filterValue && obj.filterValue.length) {
        query[obj.key] = obj.filterValue
      }
    }
  })
  state.query = query
}
/**
 * 获取表格数据
 */
const useGetTableDatas = (props, state) => {
  state.loading = true
  const { setStorageFilter } = useStorageFilter(props, state)
  const {
    interfaceURL,
    hasPaginate,
    beforeReqLoad,
    afterRespLoad,
    method,
    isRenderTableData
  } = props
  let curPaginate = hasPaginate ? paginate.value : {}
  const serveParams = {
    ...curPaginate,
    ...state.localApiParams,
    ...state.query
  }
  setStorageFilter()
  if (beforeReqLoad) {
    beforeReqLoad(serveParams)
  }
  const fn = method === 'get' ? get : post

  const fetchData = async () => {
    let tableDatas = []
    try {
      const { success, data } = await fn(
        `${process.env.VUE_APP_CONFIG}/${interfaceURL}`,
        serveParams
      ).finally(() => {
        state.loading = false
      })
      if (success) {
        if (Object.prototype.toString.call(data) === '[object Object]') {
          tableDatas = data.list || []
        } else {
          tableDatas = data || []
        }
        if (isRenderTableData) {
          state.vxeDatas = tableDatas
        }

        paginate.value.total = data?.total || 0
        // pageInfo.pageSize = data.pageSize
        const $table = tableDom.value
        if ($table && state.selectedRowsMap[paginate.value.pageNum]) {
          $table.setCheckboxRow(
            state.selectedRowsMap[paginate.value.pageNum],
            true
          )
        }
      } else {
        state.vxeDatas = []
      }
      if (afterRespLoad) {
        nextTick(() => {
          afterRespLoad(tableDatas)
        })
      }
    } catch (error) {
      console.error(error)
    }
  }
  fetchData()
}
/**
 * 搜索表格
 * @param {*} props
 */
const useTableSearch = (props, state) => {
  useFilterParams(state)
  useGetTableDatas(props, state)
}
/**
 * 处理表格的相关操作问题
 */
const useTableOperate = (props, state, emits) => {
  const { clearFilter } = useTableFilter(props, state)
  // 多选框
  const selectChangeEvent = ({ checked }) => {
    const $table = tableDom.value
    if ($table) {
      const records = $table.getCheckboxRecords()
      state.selectedRowsMap[paginate.value.pageNum] = records
      console.log(checked ? '勾选事件' : '取消事件', records)
    }
  }
  // 单选
  const radioChangeEvent = ({ row }) => {
    // const $table = tableDom.value
    state.selectedRowKeys = [row[props.rowKey]]
    state.selectedRows = [row]
    state.selectedRowsMap = {
      [paginate.value.pageNum]: state.selectedRows
    }
  }
  /**
   * 获取单选复选的值
   * @param {*} val
   */
  const getCheckboxRecords = val => {
    state.selectedRowKeys = []
    state.selectedRows = []
    if (val) {
      const keys = Object.keys(val)
      state.selectedRows = keys.reduce((prev, cur) => {
        return [...prev, ...val[cur]]
      }, [])
      state.selectedRowKeys = state.selectedRows.map(item => item[props.rowKey])
    }
  }
  // 取消选择
  const onCancelSelect = () => {
    const $table = tableDom.value
    state.selectedRowKeys = []
    state.selectedRows = []
    state.selectedRowsMap = {}
    if ($table) {
      $table?.clearCheckboxRow()
      $table?.clearRadioRow()
    }
  }
  // 导出
  const exportExcel = () => {
    state.exportLoading = true
    emits(
      'export',
      {
        ...props.apiParams,
        ...state.query
      },
      paginate.value
    )
    setTimeout(() => {
      state.exportLoading = false
    }, 1000)
  }
  // 刷新页面，保留用户操作
  const refresh = apiParams => {
    if (
      apiParams &&
      Object.prototype.toString.call(apiParams) === '[object Object]'
    ) {
      state.localApiParams = apiParams
    }
    props.interfaceURL && useGetTableDatas(props, state)
    onCancelSelect()
    emits('refresh')
  }
  // 重置页面
  const reset = apiParams => {
    if (
      apiParams &&
      Object.prototype.toString.call(apiParams) === '[object Object]'
    ) {
      state.localApiParams = apiParams
    }
    paginate.value.pageNum = 1
    // paginate.value.pageSize = props.pageSize
    state.query = { sortList: [] }
    clearFilter()
    onCancelSelect()
    props.interfaceURL && useGetTableDatas(props, state)
    emits('reset')
  }
  // 分页
  const changePage = (page, size) => {
    paginate.value.pageNum = page
    paginate.value.pageSize = size
    useGetTableDatas(props, state)
  }
  // 列设置刷新列
  const refreshColumn = () => {
    state.vxeColumns = []
    useGetvxeColumns(props, state)
    useGetTableDatas(props, state)
  }
  const printSelectEvent = () => {
    const $table = tableDom.value
    if ($table) {
      $table.print({
        sheetName: '打印勾选行',
        // 打印样式设置
        style: '',
        // mode: 'selected',
        // 打印指定列
        columns: $table.getColumns(),
        beforePrintMethod: ({ content }) => {
          // 打印之前，返回自定义的 html 内容
          return content
        }
      })
    }
  }
  /**
   * 计算列宽
   * @param {*} item
   * @returns
   */
  const calcColumnWidth = item => {
    const { title, dataIndex } = item
    if (item.width || item.minWidth) {
      return item.width || item.minWidth
    }
    if (props.isCustomWidth) {
      return useColumnWidth(
        {
          columnName: title,
          requestStr: dataIndex,
          isSearched: 1
        },
        props
      )
    }
    return 'auto'
  }
  return {
    radioChangeEvent,
    onCancelSelect,
    exportExcel,
    refresh,
    reset,
    changePage,
    selectChangeEvent,
    getCheckboxRecords,
    refreshColumn,
    printSelectEvent,
    calcColumnWidth
  }
}
/**
 * 处理表格筛选条件
 * @param {*} props
 * @returns
 */
const useTableFilter = (props, state) => {
  /**
   * 根据查询条件获取列筛选数据
   * @param {*} item
   */
  const getColumnFilterData = async function (item) {
    const result = await config_list_column_post(item.params)
    if (state.query[item.key] && state.query[item.key].length > 0) {
      item.filterValue = state.query[item.key] || []
    }
    if (item.searchValue) {
      item.plainOptions = result.data.filter(
        t =>
          t.value &&
          t.value.toLowerCase().includes(item.searchValue.trim().toLowerCase())
      )
    } else {
      item.plainOptions = result.data
    }
    state.options = result.data
  }

  /**
   * 筛选弹框弹出
   * @param {*} param0
   */
  const filterVisibleEvent = ({ column }) => {
    let columnIndex = -1,
      colgroupIndex = -1

    state.vxeColumns.forEach((item, index) => {
      if (item.dataIndex === column.field) {
        columnIndex = index
      } else if (item.colgroup) {
        const colIndex = item.colgroup.findIndex(
          col => col.dataIndex === column.field
        )
        if (colIndex > -1) {
          colgroupIndex = colIndex
          columnIndex = index
        }
      }
    })

    // const columns = state.vxeColumns.reduce((prev, cur) => {
    //   const arr = cur.colgroup ? cur.colgroup : [cur]
    //   return [...prev, ...arr]
    // }, [])
    // const vxecolumn = columns.find(item => item.dataIndex === column.field)
    const vxecolumn =
      colgroupIndex > -1
        ? state.vxeColumns[columnIndex].colgroup[colgroupIndex]
        : state.vxeColumns[columnIndex]
    if (props.queryFields?.length) {
      vxecolumn.params.queryFields = props.queryFields
    }
    if (![1].includes(vxecolumn.model)) {
      getColumnFilterData(vxecolumn)
    }
  }
  const filterSearchEvent = () => {
    paginate.value.pageNum = 1
    useTableSearch(props, state)
    closeFilterEvent()
  }
  const clearFilter = () => {
    state.vxeColumns.forEach((item, index) => {
      if (item.colgroup) {
        item.colgroup.forEach((item, colgroupIndex) => {
          resetColumnFilter(index, colgroupIndex)
        })
      }
      resetColumnFilter(index)
    })
  }
  // 重置列条件信息
  const resetColumnFilter = (index, colgroupIndex) => {
    const obj =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    obj.filterValue = []
    obj.indeterminate = false
    obj.checkAll = false
    obj.desc = ''
    obj.searchValue = null
    obj.isBatch = false
    obj.isBlank = false
    if (obj.params) {
      obj.params.queryStr = ''
    }
    obj.batchTags = []
  }
  const onChange = (checkedList, index, colgroupIndex) => {
    const obj =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    const item = obj
    obj.checkAll = checkedList.length === item.plainOptions.length
    obj.indeterminate =
      !!checkedList.length && checkedList.length < item.plainOptions.length
  }
  /**
   * 关闭筛选弹框
   */
  const closeFilterEvent = () => {
    const $table = tableDom.value
    if ($table) {
      $table.closeFilter()
    }
  }
  const openFilterEvent = column => {
    const $table = tableDom.value
    if ($table) {
      $table.openFilter(column.field)
    }
  }
  const handleReset = (index, colgroupIndex) => {
    resetColumnFilter(index, colgroupIndex)
    filterSearchEvent()
  }
  const handleSearch = (index, colgroupIndex) => {
    colgroupIndex !== undefined
      ? (state.vxeColumns[index].colgroup[colgroupIndex].isBatch = false)
      : (state.vxeColumns[index].isBatch = false)
    filterSearchEvent()
  }
  // 设置筛选空数据
  const setBlank = (e, index, colgroupIndex) => {
    const item =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    item.isBlank = e.target.checked
    colgroupIndex !== undefined
      ? (state.vxeColumns[index].colgroup[colgroupIndex] = item)
      : (state.vxeColumns[index] = item)
  }
  // 全选
  const onCheckAllChange = (e, index, colgroupIndex) => {
    const item =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    item.checkAll = e.target.checked
    item.indeterminate = false
    item.filterValue = e.target.checked ? item.plainOptions.map(e => e.key) : []
    colgroupIndex !== undefined
      ? (state.vxeColumns[index].colgroup[colgroupIndex] = item)
      : (state.vxeColumns[index] = item)
  }
  // 输入框本地模糊匹配搜索
  const inputSearch = debounce(function (e, index, colgroupIndex) {
    const obj =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    if (e.target.value) {
      obj.plainOptions = state.options.filter(
        _ =>
          _.value &&
          _.value.toLowerCase().includes(e.target.value.trim().toLowerCase())
      )
    } else {
      obj.plainOptions = state.options
    }
  }, 300)
  // 远程搜索
  const remoteSearch = debounce(function (e, index, colgroupIndex) {
    const item =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    item.params.queryStr = e.target.value ? e.target.value.trim() : ''
    getColumnFilterData(item)
  }, 300)

  // 批量查询输入失去焦点
  const handlerBatchBlur = (e, index, colgroupIndex) => {
    const obj =
      colgroupIndex !== undefined
        ? state.vxeColumns[index].colgroup[colgroupIndex]
        : state.vxeColumns[index]
    const batchTags = obj.batchTags
    if (!batchTags) {
      obj.batchTags = []
    }
    const valueStr = e.target.value.replaceAll(/\t|\n|\s+/g, ' ')
    const values = valueStr.split(' ').filter(item => {
      return item.trim() !== ''
    })
    obj.batchTags = [...new Set(obj.batchTags.concat(values))]
    obj.batchValue = null
  }
  // 删除输入记录
  const handlerDelBatchItem = (index, columnIndex, colgroupIndex) => {
    colgroupIndex !== undefined
      ? state.vxeColumns[columnIndex][columnIndex].batchTags.splice(index, 1)
      : state.vxeColumns[columnIndex].batchTags.splice(index, 1)
  }
  const handleBatchSearch = (
    comfirm,
    column,
    isBatch,
    index,
    colgroupIndex
  ) => {
    if (index >= 0) {
      resetColumnFilter(index, colgroupIndex)
    }
    column.isBatch = isBatch
    filterSearchEvent()
  }
  const handleSort = (sort, index, colgroupIndex) => {
    colgroupIndex !== undefined
      ? (state.vxeColumns[index].colgroup[colgroupIndex].desc = sort)
      : (state.vxeColumns[index].desc = sort)
    useTableSearch(props)
    closeFilterEvent()
  }
  const queryAllParams = () => {
    return {
      ...props.apiParams,
      ...state.query,
      ...paginate.value
    }
  }
  return {
    onChange,
    remoteSearch,
    handleSearch,
    handleReset,
    setBlank,
    onCheckAllChange,
    inputSearch,
    handlerBatchBlur,
    handleBatchSearch,
    handlerDelBatchItem,
    handleSort,
    openFilterEvent,
    filterVisibleEvent,
    clearFilter,
    queryAllParams
  }
}
/**
 * 处理表格watch
 * @param {*} props
 * @param {*} emits
 */
const useTableWatchData = (props, state, emits) => {
  const { getCheckboxRecords } = useTableOperate(props, state, emits)
  // 双向绑定当前页的表格数据
  watch(
    () => state.vxeDatas,
    val => {
      emits('update:value', val)
    },
    {
      deep: true
    }
  )
  watch(
    () => props.value,
    val => {
      state.vxeDatas = val || []
    },
    {
      immediate: true,
      deep: true
    }
  )
  watch(
    () => props.columns,
    val => {
      if (val) {
        state.vxeColumns = val
      }
    },
    {
      immediate: true,
      deep: true
    }
  )
  watch(
    () => state.vxeColumns,
    val => {
      if (val) {
        emits('update:columns', val)
      }
    },
    {
      deep: true
    }
  )
  watch(
    () => state.selectedRowsMap,
    val => {
      getCheckboxRecords(val)
      emits('change', state.selectedRowKeys, state.selectedRows)
    },
    {
      deep: true
    }
  )
  watch(
    () => props.loading,
    val => {
      state.loading = val
    },
    {
      immediate: true
    }
  )
}
/**
 * 处理表格挂载
 * @param {*} props
 */
const useTableMounted = (props, state) => {
  const { menuName, interfaceURL, immediate } = props
  onMounted(() => {
    useInitState(props, state)
    menuName && useGetvxeColumns(props, state)
    interfaceURL && immediate && useGetTableDatas(props, state)
  })
}

export const useTable = (props, emits) => {
  const state = useState()
  useTableWatchData(props, state, emits)
  useTableMounted(props, state)

  return {
    state,
    ...useTableOperate(props, state, emits),
    ...useTableFilter(props, state)
  }
}
